﻿using System;
using System.Collections;
using System.Collections.Generic;

using zijian666.Converts.Abstractions;
using zijian666.Converts.Convertor;
using zijian666.Converts.Convertor.Base;
using zijian666.Converts.Core;
using zijian666.Converts.Extensions;

namespace zijian666.Converts.Factory;

/// <summary>
/// <see cref="ListConvertor{TList, TValue}"/> 工厂
/// </summary>
public sealed class ListConvertorFactory : IConvertorFactory
{
    /// <inheritdoc/>
    public MatchedConvertor<T> Create<T>()
    {
        if (typeof(T).IsArray)
        {
            return default;
        }
        var type = typeof(T);
        var genericArgs = type.GetGenericArguments(typeof(IList<>));
        if (genericArgs is not null)
        {
            var matchedType = type.MatchType(typeof(List<>).MakeGenericType(genericArgs[0]), typeof(IList<>).MakeGenericType(genericArgs[0]));

            switch (matchedType)
            {
                case MacthedType.Equals:
                    var convertor1 = (IConvertor<T>)Activator.CreateInstance(typeof(ListConvertor<,>).MakeGenericType(type, genericArgs[0]));
                    return new MatchedConvertor<T>(convertor1, MacthedType.Equals);
                case MacthedType.Acceptable:
                    var convertor2 = (IConvertor<T>)Activator.CreateInstance(typeof(ListConvertor<,>).MakeGenericType(type, genericArgs[0]));
                    return new MatchedConvertor<T>(convertor2, MacthedType.Acceptable);
                case MacthedType.TryCreate:
                    var convertor3 = (IConvertor<T>)Activator.CreateInstance(typeof(ListConvertor<,>).MakeGenericType(type, genericArgs[0]));
                    return new MatchedConvertor<T>(convertor3, MacthedType.TryCreate);
                case MacthedType.NotMatched:
                default:
                    break;
            }
        }

        switch (type.MatchType(typeof(ArrayList), typeof(IList)))
        {
            case MacthedType.Equals:
                var convertor1 = (IConvertor<T>)Activator.CreateInstance(typeof(ArrayListConvertor<>).MakeGenericType(type));
                return new MatchedConvertor<T>(convertor1, MacthedType.Equals);
            case MacthedType.Acceptable:
                if (typeof(IList).IsAssignableFrom(type))
                {
                    var convertor2 = (IConvertor<T>)Activator.CreateInstance(typeof(ArrayListConvertor<>).MakeGenericType(type));
                    return new MatchedConvertor<T>(convertor2, MacthedType.Acceptable);
                }
                else if (type != typeof(object))
                {
                    var convertor2 = new ArrayListConvertor<ArrayList>();
                    var proxy = (IConvertor<T>)Activator.CreateInstance(typeof(ProxyConvertor<,>).MakeGenericType(typeof(ArrayList), typeof(T)), convertor2);
                    return new MatchedConvertor<T>(proxy, MacthedType.Acceptable);
                }
                break;
            case MacthedType.TryCreate:
                var convertor3 = (IConvertor<T>)Activator.CreateInstance(typeof(ArrayListConvertor<>).MakeGenericType(type));
                return new MatchedConvertor<T>(convertor3, MacthedType.TryCreate);
            case MacthedType.NotMatched:
            default:
                break;
        }

        return default;
    }
}
